package com.yomahub.liteflow.example.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.ftp.Ftp;
import com.yomahub.liteflow.example.config.UploadFtpConfig;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: qar-cloud
 * @description: gzip压缩
 * @author: yyyyjinying
 * @create: 2023-11-28 18:35
 **/
@Component
public class PackUtils {
    @Autowired
    private UploadFtpConfig uploadFtpConfig;

    /**
     * 上传集合字符串到FTP的GZ压缩文件中
     * List<String> list = Arrays.asList("我我fdfd", "fdfd!");
     * boolean b = packUtils.uploadListStrToFTP(list, "/ftp/demo8.gz");
     * @param list
     * @param path
     * @return
     */
    public boolean uploadListStrToFTP(List<String> list, String path) {
        Boolean ok = false;
        String fileName = new File(path).getName();
        String prefix = fileName.substring(0, fileName.lastIndexOf("."));

        Ftp ftp = uploadFtpConfig.getFtp();
        FTPClient client = ftp.getClient();
        try {
            client.setFileType(FTP.BINARY_FILE_TYPE);
            File tempFile = File.createTempFile(prefix, ".txt");

            FileUtil.writeLines(list, tempFile, Charset.forName("UTF-8"));

            File tempInputFile = File.createTempFile(prefix, ".gz");
            try (OutputStream outputStream = new FileOutputStream(tempInputFile);
                 GzipCompressorOutputStream gzipCompressorOutputStream = new GzipCompressorOutputStream(outputStream)) {
                try (InputStream inputStream = new FileInputStream(tempFile);) {
                    TarArchiveOutputStream tarArchiveOutputStream = new TarArchiveOutputStream(gzipCompressorOutputStream);
                    TarArchiveEntry archiveEntry = new TarArchiveEntry(tempFile, tempFile.getName());
                    tarArchiveOutputStream.putArchiveEntry(archiveEntry);
                    IOUtils.copy(inputStream, tarArchiveOutputStream);
                    tarArchiveOutputStream.closeArchiveEntry();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }


            // 上传临时文件到压缩文件
            try (InputStream inputStream = new FileInputStream(tempInputFile)) {
                ok = client.storeFile(path, inputStream);;
            }catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                // 删除临时文件
                tempInputFile.delete();
                tempFile.delete();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                ftp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return ok;
    }

    /**
     * 将gz文件下载到临时文件 uploadFtpConfig.getTmpFilePath()
     * packUtils.getFileFromFTP("/ftp/demo1.gz");
     * @param path
     * @return
     */
    public List<String> getFileFromFTP(String path) {
        Ftp ftp = uploadFtpConfig.getFtp();
        String fileName = new File(path).getName();
        String dir = path.substring(0, path.lastIndexOf(fileName));
        String targetFilename = fileName.substring(0, fileName.lastIndexOf(".")) + ".txt";
        FTPClient client = ftp.getClient();
        InputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        List<String> list = new ArrayList<>();
        try {
            boolean bol = client.changeWorkingDirectory(dir);
            if (bol) {
                FTPFile[] ftpFiles = client.listFiles();
                for (FTPFile ftpFile : ftpFiles) {
                    if (ftpFile.isFile() && ftpFile.getName().equals(fileName)) {
                        inputStream = client.retrieveFileStream(path);
                        TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(new GzipCompressorInputStream(inputStream));
                        TarArchiveEntry tarArchiveEntry = null;
                        while ((tarArchiveEntry = tarArchiveInputStream.getNextTarEntry()) != null) {
                            // 输出到文本
                            if (tarArchiveEntry.isFile()) {
                                fileOutputStream = new FileOutputStream(new File(uploadFtpConfig.getTmpFilePath(), targetFilename));
                                byte[] buffer = new byte[1024];
                                int bytesRead;
                                while ((bytesRead = tarArchiveInputStream.read(buffer)) != -1) {
                                    fileOutputStream.write(buffer, 0, bytesRead);
                                }
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                ftp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return list;
    }


    /**
     * 读取gz压缩包中的集合数据
     * List<String> listStrFromFile = packUtils.getListStrFromFTP("/ftp/demo8.gz");
     * @param path
     * @return
     */
    public List<String> getListStrFromFTP(String path) {
        Ftp ftp = uploadFtpConfig.getFtp();
        String fileName = new File(path).getName();
        String dir = path.substring(0, path.lastIndexOf(fileName));
        FTPClient client = ftp.getClient();
        InputStream inputStream = null;
        List<String> list = new ArrayList<>();
        try {
            boolean bol = client.changeWorkingDirectory(dir);
            if (bol) {
                FTPFile[] ftpFiles = client.listFiles();
                for (FTPFile ftpFile : ftpFiles) {
                    if (ftpFile.isFile() && ftpFile.getName().equals(fileName)) {
                        // 取回文件
                        inputStream = client.retrieveFileStream(path);
                        TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(new GzipCompressorInputStream(inputStream));
                        TarArchiveEntry tarArchiveEntry = null;
                        while ((tarArchiveEntry = tarArchiveInputStream.getNextTarEntry()) != null) {
                            if (tarArchiveEntry.isFile()) {
                                // 将tarArchiveInputStream转化为字符串输入流
                                BufferedReader reader = new BufferedReader(new InputStreamReader(tarArchiveInputStream));
                                String line;
                                while ((line = reader.readLine()) != null) {
                                    list.add(line);
                                }
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                ftp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return list;
    }
}
